<template>
	<view>
		<view class="grid">
			<view class="grid-item" v-for="(item, index) in modelValue" :key="index">
				<image
					class="image"
					v-if="item.url || item.path"
					:src="item.url || staticUrl + item.path"
					mode="aspectFill"
					:data-url="item.url || staticUrl + item.path"
					@tap="viewImage"
				></image>
				<view class="image-delete" v-if="!disabled" @tap.stop="delImg" :data-index="index">
					<uni-icons class="clearicon" :size="20" color="#e43d33" type="clear"></uni-icons>
				</view>
			</view>
			<view class="grid-item" v-if="tempFilePath">
				<image class="image" :src="tempFilePath" mode="aspectFill"></image>
				<view class="progress-box" v-if="progress">
					<progress :percent="progress" :activeColor="showError ? '#dd524d' : '#4cd964'" stroke-width="3" />
				</view>
				<view class="upload-error" v-if="showError">
					<text>上传失败</text>
				</view>
			</view>
			<view class="grid-item" @tap="chooseImage" v-if="modelValue.length < maxCount && !disabled">
				<uni-icons class="addicon" :size="38" color="#d9d9d9" type="plusempty"></uni-icons>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, onMounted } from 'vue';
const props = defineProps({
	modelValue: {
		type: Array,
		default() {
			return [];
		}
	},
	// 文件上传地址
	uploadUrl: {
		type: String,
		default: ''
	},
	// 文件访问跟地址
	staticUrl: {
		type: String,
		default: ''
	},
	// 最大上传数量
	maxCount: {
		type: Number,
		default: 5
	},
	// 是否禁用
	disabled: {
		type: Boolean,
		default: false
	},
	// 选择图片
	choose: {
		validator: function (value) {
			if (value) {
				return typeof value === 'function';
			} else {
				return true;
			}
		},
		require: true,
		default: false
	},
	// 额外请求参数
	params: {
		validator: function (value) {
			if (value) {
				return typeof value === 'object' || typeof value === 'function';
			} else {
				return true;
			}
		},
		default() {
			return {};
		}
	},
	// 请求头
	headers: {
		validator: function (value) {
			if (value) {
				return typeof value === 'object' || typeof value === 'function';
			} else {
				return true;
			}
		},
		default() {
			return {};
		}
	}
});
const tempFilePath = ref('');
const progress = ref(0);
const showError = ref(false);

const emits = defineEmits(['update:modelValue', 'change']);

/**
 * 选择图片
 */
const chooseImage = () => {
	props.choose().then((res) => {
		fileUpload(res);
	});
};

/**
 * 选择完成
 */
const fileUpload = (tempath) => {
	tempFilePath.value = tempath;
	uni.showLoading({
		title: '正在上传...'
	});
	let param = {};
	if (props.params) {
		if (typeof props.params === 'function') {
			param = props.params();
		} else if (typeof props.params === 'object') {
			param = props.params;
		}
	}
	let header = {};
	if (props.headers) {
		if (typeof props.headers === 'function') {
			header = props.headers();
		} else if (typeof props.headers === 'object') {
			header = props.headers;
		}
	}
	const task = uni.uploadFile({
		url: props.uploadUrl,
		filePath: tempath,
		name: 'file',
		formData: param,
		header: header,
		success: (result) => {
			console.log(result);
			if (result.statusCode != 200) {
				/* 失败 */
				uploadError();
				return;
			}
			let res = result.data;
			if (res instanceof String || typeof res === 'string') {
				res = JSON.parse(res);
			}
			if (res.code != 1) {
				uploadError();
				return;
			}
			const data = res.data;
			if (!(data.url || data.path)) {
				uploadError();
				return;
			}
			uploadSuccess(data);
		},
		fail: () => {
			uploadError();
		}
	});
	// 上传进度监听
	task.onProgressUpdate((res) => {
		if (res.progress > 0) {
			progress.value = res.progress;
		}
	});
};
/**
 * 文件上传失败处理
 */
const uploadError = () => {
	uni.hideLoading();
	showError.value = true;
	uni.showToast({
		icon: 'error',
		title: '上传失败'
	});
	setTimeout(() => {
		tempFilePath.value = '';
	}, 1500);
};
/**
 * 文件上传成功
 */
const uploadSuccess = (data) => {
	tempFilePath.value = '';
	emits('update:modelValue', [...props.modelValue, data]);
	emits('change', [...props.modelValue, data]);
	uni.hideLoading();
	uni.showToast({
		icon: 'success',
		title: '上传成功'
	});
};
/* 预览 */
const viewImage = (e) => {
	const urls = [];
	props.modelValue.forEach((v) => {
		urls.push(v.url || props.staticUrl + v.path);
	});
	uni.previewImage({
		urls: urls,
		current: e.currentTarget.dataset.url
	});
};
/* 删除 */
const delImg = (e) => {
	const index = e.currentTarget.dataset.index;
	uni.showModal({
		title: '提示',
		content: '您确定要删除此项吗？',
		success: (res) => {
			if (res.confirm) {
				const imageList = props.modelValue;
				imageList.splice(index, 1);
				emits('update:modelValue', imageList);
				emits('change', imageList);
			}
		}
	});
};

onMounted(() => {
	/**
	 * 环境判断
	 */
	let target = navigator.userAgent.toLowerCase();
	let isWeixin = /micromessenger/.test(target);
	if (!isWeixin) {
		uni.showModal({
			title: '请在微信浏览器下使用',
			content: '该页面仅支持微信环境！！！',
			showCancel: false
		});
	}
});
</script>

<style scoped lang="scss">
.grid {
	display: flex;
	flex-wrap: wrap;
	overflow: hidden;

	.grid-item {
		padding-bottom: calc((100% - 72rpx) / 3);
		height: 0;
		width: calc((100% - 72rpx) / 3);
		margin-right: 20rpx;
		margin-top: 20rpx;
		border-radius: 6rpx;
		overflow: hidden;
		position: relative;
		// background-color: #f0f0f0;
		border: 1rpx solid #d9d9d9;

		&:nth-child(4n) {
			margin-right: 0;
		}

		.image-delete {
			position: absolute;
			right: 2rpx;
			top: 2rpx;
		}

		.progress-box {
			position: absolute;
			bottom: 0;
			left: 0;
			width: 100%;
		}

		.upload-error {
			position: absolute;
			width: 100%;
			font-size: 14px;
			color: #e43d33;
			text-align: center;
			background-color: rgba(0, 0, 0, 0.5);
		}

		.image {
			width: 100%;
			height: 100%;
			position: absolute;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
		}

		.addicon {
			position: absolute;
			margin: auto;
			top: 0;
			bottom: 0;
			left: 0;
			right: 0;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: column;
			border-radius: 6rpx;
			// border: 1rpx solid #d9d9d9;
		}
	}
}
</style>
